"""
Thie class defines some custom interaction callbacks for a VTK render window

The SetRenderWindow() method must be called for this to work.
"""

import vtk

class myInteractorStyle(vtk.vtkInteractorStyleTrackballActor):
    """
    This defines callbacks for the render window interaction
    """
    
    def __init__(self):
        """
        
        """
        #These objects must be set for the callbacks to work correctly
        self.textActor = []
        self.renWin = []
        self.interactor = []
        self.ren = []
        self.volume = []
        
        self.verbose = False
        
        self._Rotating = 0
        self._Panning = 0
        self._Zooming = 0
        
    def Refresh(self):
        """
        Call this function to refresh the objects.  It might need to be called 
        when the event is triggered, since the volume is not always set the 
        when SetRenderWindow is called. 
        """
        
        #Try to get all other necessary object from the render window
        try:
            renderers = self.renWin.GetRenderers()
            self.ren = renderers.GetItemAsObject(0)
            
            volumes = self.ren.GetVolumes()
            self.volume = volumes.GetItemAsObject(0)
            
            actors = self.ren.GetActors2D()
            self.textActor = actors.GetItemAsObject(0)
            
            self.interactor = self.renWin.GetInteractor()
        except:
            print "There was an error setting the necessary objects for callbacks to function"
            
        if self.verbose:
            print self.ren.__class__
            print self.volume.__class__
            print self.textActor.__class__
            print self.interactor.__class__
            
            
    def SetRenderWindow(self, renWin):
        self.renWin = renWin
        self.Refresh()
        
    def SetPoseCallback(self, obj, event):
        """
        Press 's' key to set the pose in the moving image render window
        """
        #print obj
        
        key = obj.GetKeySym()
        if key =="s":
            cam = self.ren.GetActiveCamera()
            ori = cam.GetOrientation()
            self.textActor.SetInput(str(ori))
            self.renWin.Render()
            
        else:
            pass
            self.textActor.SetInput("some key other than s pressed")
            self.renWin.Render()
           
         
    def ExitCallback(self, obj, event):
        print "An exit event was detected\n"
        self.interactor.Disable()
        
        
        
    # Add the observers to watch for particular events. These invoke
    # Python functions.
    def ButtonEventCallback(self, obj, event):
        if event == "LeftButtonPressEvent":
            self._Rotating = 1
        elif event == "LeftButtonReleaseEvent":
            self._Rotating = 0
        elif event == "MiddleButtonPressEvent":
            self._Panning = 1
        elif event == "MiddleButtonReleaseEvent":
            self._Panning = 0
        elif event == "RightButtonPressEvent":
            self._Zooming = 1
        elif event == "RightButtonReleaseEvent":
            self,_Zooming = 0


    # General high-level logic
    def MouseMoveCallback(self, obj, event):
        global iren, renWin, ren
        iren = self.interactor
        renWin = self.renWin
        ren = self.ren
        
        lastXYpos = iren.GetLastEventPosition()
        lastX = lastXYpos[0]
        lastY = lastXYpos[1]

        xypos = iren.GetEventPosition()
        x = xypos[0]
        y = xypos[1]

        center = renWin.GetSize()
        centerX = center[0]/2.0
        centerY = center[1]/2.0

        if self._Rotating:
            self.textActor.SetInput("rotating...")
            self.renWin.Render()
##            self.Rotate(self.ren, self.ren.GetActiveCamera(), 
##                x, y, lastX, lastY, centerX, centerY)
            self.Rotate()
        elif self._Panning:
            self.Pan(self.ren, self.ren.GetActiveCamera(), 
                x, y, lastX, lastY, centerX, centerY)
        elif self._Zooming:
            self.Dolly(self.ren, self.ren.GetActiveCamera(), 
                x, y, lastX, lastY, centerX, centerY)

            
    # Routines that translate the events into camera motions.

    # This one is associated with the left mouse button. It translates x
    # and y relative motions into camera azimuth and elevation commands.
##    def Rotate(self, renderer, camera, x, y, lastX, lastY, centerX, centerY):    
##    ##            camera.Azimuth(lastX-x)
##    ##            camera.Elevation(lastY-y)
##    ##            camera.OrthogonalizeViewUp()
##        self.volume.SetOrientation(lastX-x, lastY-y, 0)
##    ##            self.textActor.SetInput(str((x,y)))
##    ##            self.renWin.Render()
      

                